

import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * 随意输入一个用户名或者密码，可以登录，这种现象叫做sql注入，
 * 原因：用户不是一般的用户，是懂得程序的，输入的用户名密码信息中含有sql的关键字和底层的sql语句进行了”字符串拼接”导致原sql语句含义被改变，
 * 此时用户提供的信息参与了SQL语句的编译
 * 如用户名：s 密码：s' or '1'='1
 */
    /*
     怎么避免sql注入？
     sql注入的根本原因是，先进行了字符串的拼接，然后在进行的编译。

      java.sql.Statement接口的特点，先进行字符串的拼接。然后再进行sql语句的编译。
      优点：使用Statement可以进行sql语句的拼接。
      缺点：因为拼接的存在，导致可能给不法分子机会。

      java.sql.PreparedStatement接口的特点，先进行sql语句的编译，然后在进行sql语句的传值。
       优点：避免sql注入。
       缺点:没有办法进行sql语句的拼接，只能给sql语句传值。
       PreparedStatement预编译的数据库操作对象
    */
public class JDBCTest02 {
    public static void main(String[] args) {
        //初始化一个界面，可以让用户输入用户名和密码
        Map<String,String>userLoginInfo=initUI();
        //连接数据库验证用户和密码是否正确
        boolean ok=checkNameAndPwd(userLoginInfo.get("loginName"),userLoginInfo.get("loginPwd"));
        System.out.println(ok?"登陆成功":"登陆失败");

    }

    private static boolean checkNameAndPwd(String loginName, String loginPwd) {
        boolean ok=false;//默认登录是失败的，
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        // 1、注册驱动
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2、获取连接
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/jdbc", "root", "root");
            // 3、获取数据库操作对象
            stmt = conn.createStatement();
            // 4、执行sql语句
            String sql = "select * from t_user where login_name='"+loginName+"'and login_pwd='"+loginPwd+"'";
            System.out.println(sql);
            //程序执行到此处，才会将以上的sql语句发送到DBMS上，DBMS进行sql语句的编译。
            rs = stmt.executeQuery(sql);//sql处理后会返回一个处理集，
            //如果以上sql语句中用户名和密码是正确的，那么结果集最多也就查询出一条记录，所以以下不需要while循环。if就够了
            if(rs.next()){//此条件如果成立，表示登录成功
                ok=true;
            }
            // 5、处理结果集
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 6、释放资源
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn!= null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

        return ok;
    }


    private static Map<String, String> initUI(){
        System.out.println("欢迎使用该系统，请输入用户名和密码进行身份认证");
        Scanner s=new Scanner(System.in);
        System.out.println("用户名：");
        String loginName=s.nextLine();
        System.out.println("密码：");
        String loginPwd=s.nextLine();
        //将用户名和密码放在map集合中
        Map<String,String> useLoginInfo=new HashMap<>();
        useLoginInfo.put("loginName",loginName);
        useLoginInfo.put("loginPwd",loginPwd);
        //返回map
        return useLoginInfo;

    }

/*
随便输入一个用户名的密码，登录成功了，这种现象被称为SQL注入现象！
导致SQL注入的根本原因是：用户不是一般的用户，用户是懂程序的，输入的用户名信息以及密码信息中，
含有SQL语句的关键词，这个SQL语句的关键字和底层的SQL语句进行“字符串拼接”，导致原SQL语句的含义
被扭曲了。最最主要的原因是：用户提供的信息参与了SQL语句的编译。

主要因素，这个程序是先进行字符串的拼接，然后再进行sql语句的编译，正好彼注入。
用户名：
fdsa
密码：
fdsa' or '1'='1
select * from t_user where login_name='fdsa'and login_pwd='fdsa' or '1'='1'
 */


}

